<?php
/**
 * User: @lixu
 * Date: 2019-03-20
 * Time: 11:27
 */

namespace Biz\service\esSearch;

use Biz\service\Sku as sSku;
use Biz\model\GoodsBasicInfo as mGoodsBasicInfo;
use Biz\service\Goods as sGoods;
use Biz\model\GoodsExtendInfo as mGoodsExtendInfo;
use Doraemon\model\admTag;
use Biz\model\PhotoRelaGoods;
use Biz\model\activity\FullShippingGoods as mFullShippingGoods;
use Biz\module\Search\GoodsSearch;
use Doraemon\model\Category as mCategory;
use Doraemon\tools\HhzEnv;
use Biz\tools\IsTestShop;
use Biz\cache\LimitationShop;
use Doraemon\tools\Log;
use Biz\cache\counter\GoodsAddCart as cGoodsAddCart;
use Doraemon\amqp\Queue;
use Biz\tools\FormatDate;

class Goods
{

    const TYPE_INSERT = 'insert';
    const TYPE_UPDATE = 'update';
    const ACTIVITY_TYPE_FULL_SHIPPING = 'fs_';
    const ACTIVITY_TYPE_CHANGE_PRICE_ACTIVITY = 'cpa';
    const GOODS_TAG_SHIELD = '屏蔽商品';

    // 来源
    const SOURCE_APP = 'app';
    const SOURCE_SHOP_ADMIN = 'shop_admin';
    const SOURCE_THE_PARAGRAPH = 'the_paragraph';

    // 场景
    const SCENES_SHOP_ADMIN_TITLE = 'shop_admin_title'; // 商城管理后台根据商品名称搜索的场景 👌
    const SCENES_SHOP_ADMIN_GOODS = 'shop_admin_goods'; // 商城管理后台商品列表搜索场景  👌
    const SCENES_THE_PARAGRAPH_TAGS = 'the_paragraph_tags'; // 节选小程序分类列表页
    const SCENES_THE_PARAGRAPH_PERFECT = 'the_paragraph_perfect'; // 节选小程序分类列表页补充商品逻辑
    const SCENES_THE_PARAGRAPH_INDEX_LIST = 'the_paragraph_index_list'; // 节选小程序首页a类商品
    const SCENES_THE_PARAGRAPH_GOODS_RECOMMEND_A = 'the_paragraph_goods_recommend_a'; // 节选小程序商品详情页底部推荐商品
    const SCENES_THE_PARAGRAPH_GOODS_RECOMMEND_B = 'the_paragraph_goods_recommend_b'; // 节选小程序商品详情页底部推荐商品
    const SCENES_THE_PARAGRAPH_GOODS_RECOMMEND_C = 'the_paragraph_goods_recommend_c'; // 节选小程序商品详情页底部推荐商品
    const SCENES_THE_PARAGRAPH_PERFECT_B = 'the_paragraph_perfect_b'; // 节选小程序补品逻辑
    const SCENES_BRAND_ALL_GOODS = 'brand_all_goods'; // 获取品牌用户的商品
    const SCENES_BRAND_HOT_GOODS = 'brand_hot_goods'; // 获取品牌用户的热门商品
    const SCENES_CART_RECOMMEND = 'cart_recommend'; // 购物车推荐与过滤
    const SCENES_CATEGORY_IS_HAS_GOODS = 'category_is_has_goods'; // 查看类目下是否有商品
    const SCENES_FULL_SHIPPING = 'full_shipping'; // 满包邮列表
    const SCENES_CATEGORY_ID = 'category_id'; // 根据一级分类id查询商品
    const SCENES_GOODS_FILTER = 'goods_filter'; // 根据商品id查询
    const SCENES_MALL_TAB = 'mall_tab'; // 商城首页搜索商品
    const SCENES_SHOP_TAB = 'shop_tab'; // 商城首页搜索商品
    const SCENES_GOODS_TAG = 'goods_tag'; // 根据tag搜索商品
    const SCENES_BRAND_CATEGORY = 'brand_category'; // 根据品牌id 与 类目id 交集 取maxCounter个商品id
    const SCENES_LAST_CATEGORY_NAME = 'last_category_name'; // 根据末级分类id查询
    const SCENES_LEVEL_CATEGORY_NAME = 'level_category_name'; // 根据类目层级查询
    const SCENES_GOODS_RECOMMEND = 'goods_recommend'; // 商品详情底部推荐商品
    const SCENES_COUPON_POLYMERIZATION = 'coupon_polymerization'; // 优惠券凑单聚合页
    const SCENES_CATEGORY_LIST = 'category_list'; // 二级分类列表页

    public static function getList(array $where = [], $scenes = null, $sortType = 0, $page = 1, $pageSize = 20,  $field = ['id'], $start = null)
    {
        $result = ['total' => 0, 'is_over' => 1, 'rows' => []];

        self::filterWhere($where);

        if(is_null($scenes)) {
            return $result;
        } else {
            $where['scenes'] = $scenes;
        }

        if(!isset($where['ORDER'])) {
            $where['ORDER'] = self::sortTypeMapping($sortType);
        }

        $params['query'] = json_encode($where, JSON_UNESCAPED_UNICODE);

        if(is_array($field)) {
            $params['fl'] = implode(",", $field);
        } else {
            $params['fl'] = $field;
        }

        $params['page'] = $page;
        $params['page_size'] = $pageSize;

        $result = GoodsSearch::getList($params);

        if(isset($result['data'])) {
            $result = $result['data'];
            $list['total'] = $result['hits']['total'];
            $list['rows'] = $result['hits']['total'] ? self::formatGoodsList($result['hits']['hits'], $field) : [];
            $list['is_over'] = count($result['hits']['hits']) >= $pageSize ? 0 : 1;
            return $list;
        } else {
            return ['total' => 0, 'is_over' => 1, 'rows' => []];
        }
    }



    private static function sortTypeMapping($sortType)
    {
        $sortMapping = [
            [
                'sell_total' => 'DESC',
                'heat_degree' => 'DESC',
                'first_online_time' => 'DESC'
            ],
            ['first_online_time' => 'DESC'],
            ['min_price_has_stock' => 'ASC'],
            ['min_price_has_stock' => 'DESC']
        ];

        return $sortMapping[$sortType];
    }

    /**
     * 上层代码控制要同步的数据
     * @param $goodsInfo
     * @return bool
     */
    public static function saveByGoodsId($goodsInfo)
    {
        if(!$goodsInfo['id']) {
            return false;
        }

        $result = GoodsSearch::save($goodsInfo);

        if($result['code'] != 1) {
            Queue::insertQueue("queue/Wechatnotice/toTag", [
                "totag" => \Biz\pockets\constInterface\BizWechatTagConfig::TAG_BIZ_RD_SYSTEM,
                "content" => 'goods表 同步数据失败 ' . $result
            ], Queue::QUEUE_BIZ);
        }

        return $result;
    }

    /**
     * 监听binlog同步数据
     * @param $list
     */
    public static function syncSave($list)
    {
        $info = [];
        switch ($list['table']) {
            case 'goods_basic_info' :
                $info = self::formatGoodsBasicInfo($list['type'], $list['data']);
                break;
            case 'goods_sku' :
                $info = self::formatGoodsSkuInfo($list['data']);
                break;
            case 'goods_extend_info' :
                $info = self::formatGoodsExtendInfo($list['data']);
                break;
            case 'full_shipping_goods' :
                $info = self::formatFullShippingGoods($list['data']);
                break;
            case 'goods_tag' :
                $info = self::formatGoodsTagInfo($list['type'], $list['data']);
                break;
            case 'cart' :
                $info = self::formatCartInfo($list['type'], $list['data'], $list['old']);
                break;
        }

        $result = GoodsSearch::save($info);

        Log::debug('goods_basic_info-debug', $result);

        if($result['code'] != 1) {
            Queue::insertQueue("queue/Wechatnotice/toTag", [
                "totag" => \Biz\pockets\constInterface\BizWechatTagConfig::TAG_BIZ_RD_SYSTEM,
                "content" => $list['table'] . '表 同步数据失败 ' . $result,
                'addtime' => date("Y-m-d H:i:s")
            ], Queue::QUEUE_BIZ);
        }
    }

    private static function formatGoodsBasicInfo($type, $data)
    {
        $goodsId = $data['goods_id'];

        $skuBasicInfos = sSku::SkuInfos([$goodsId], sSku::FIELDS_GROUP_BASE_WITH_STOCK)[$goodsId];
        $categoryIds = [$data['category_id'], $data['second_category_id'], $data['third_category_id'], $data['four_category_id']];
        $categoryList = array_column(mCategory::getCategoryList($categoryIds, null), null, 'id');
        // 添加数据的时候，需要将所有的字段都同步过去
        if($type == self::TYPE_INSERT) {
            $info = [
                'category_name' => $categoryList[$data['category_id']]['cate_name'],
                'second_category_name' => $categoryList[$data['second_category_id']]['cate_name'],
                'third_category_name' => isset($categoryList[$data['third_category_id']]['cate_name']) ?$categoryList[$data['third_category_id']]['cate_name']: '',
                'four_category_name' => isset($categoryList[$data['four_category_id']]['cate_name']) ?$categoryList[$data['four_category_id']]['cate_name']: '',
                'last_category_name' => $categoryList[$data['last_category_id']]['cate_name'],
                'min_price_has_stock' => $skuBasicInfos['min_price']??$data['min_price'],
                'max_price_has_stock' => $skuBasicInfos['max_price']??$data['max_price'],
                'is_alarm' => self::TYPE_INSERT == $type ? 0 : (int)mGoodsBasicInfo::admIsAlarm($goodsId),
                'app_status' => mGoodsBasicInfo::STATUS_APP_MAP[$data['status']],
                'add_cart_num' => self::TYPE_INSERT == $type ? 0 : sGoods::admGetAddCartNums($goodsId),
                'counter_rela_photos' => self::TYPE_INSERT == $type ? 0 : (int)PhotoRelaGoods::getRelaCounter($goodsId),
                'material' => '',
                'style' => '',
                'tags_content' => '',
                'activity' => '',
                'heat_tag' => '',
                'heat_degree' => 0
            ];
        } else {
            $info = [
                'third_category_name' => isset($categoryList[$data['third_category_id']]['cate_name']) ?$categoryList[$data['third_category_id']]['cate_name']: '',
                'four_category_name' => isset($categoryList[$data['four_category_id']]['cate_name']) ?$categoryList[$data['four_category_id']]['cate_name']: '',
                'last_category_name' => $categoryList[$data['last_category_id']]['cate_name'],
                'min_price_has_stock' => $skuBasicInfos['min_price'],
                'max_price_has_stock' => $skuBasicInfos['max_price'],
                'is_alarm' => (int)mGoodsBasicInfo::admIsAlarm($goodsId),
                'app_status' => mGoodsBasicInfo::STATUS_APP_MAP[$data['status']],
                'counter_rela_photos' => (int)PhotoRelaGoods::getRelaCounter($goodsId),
            ];
        }

        $info = array_merge(['id' => $goodsId], $data, $info);
        $info['addtime'] = FormatDate::formatDate($info['addtime']);
        $info['operate_time'] = FormatDate::formatDate($info['operate_time']);
        $info['first_online_time'] = FormatDate::formatDate($info['first_online_time']);

        Log::debug('goods_basic_info-debug', $info);

        return $info;
    }

    private static function formatGoodsSkuInfo($data)
    {
        $goodsId = $data['goods_id'];
        $skuBasicInfos = sSku::SkuInfos([$goodsId], sSku::FIELDS_GROUP_BASE_WITH_STOCK)[$goodsId];

        $info = [
            'id' => $goodsId,
            'min_price_has_stock' => $skuBasicInfos['min_price'],
            'max_price_has_stock' => $skuBasicInfos['max_price'],
        ];

        Log::debug('goods_sku-debug', $info);

        return $info;
    }

    private static function formatGoodsExtendInfo($data)
    {
        $goodsId = $data['goods_id'];
        $extendInfo = mGoodsExtendInfo::getExtendInfosByGoodsIds($goodsId)[$goodsId];

        $material = $extendInfo['material_content'] ? implode(' ', array_column(json_decode($extendInfo['material_content'], true), 'content')) : '';
        $style = $extendInfo['style_content'] ? str_replace(",", " ", admTag::getsTagBysIds($extendInfo['style_content'])) : [];
        $tagsContent = $extendInfo['tags_content'] ? str_replace(",", " ", $extendInfo['tags_content']) : '';

        $info = [
            'id' => $goodsId,
            'material' => $material,
            'style' => $style,
            'tags_content' => $tagsContent
        ];

        Log::debug('goods_extend-debug', $info);

        return $info;
    }

    private static function formatFullShippingGoods($data)
    {
        $shippingGoods = self::ACTIVITY_TYPE_FULL_SHIPPING . $data['shipping_id'];

        $goodsInfo = GoodsSearch::getInfo($data['goods_id']);
        $activity = isset($goodsInfo['activity']) ? $goodsInfo['activity'] : '';

        // 如果状态修改为0或者9的话，需要把满包邮的数据从es的活动字段中删除
        if($activity) {
            if($data['status'] == mFullShippingGoods::STATUS_DELETE || $data['status'] = mFullShippingGoods::STATUS_INVALID) {
                $activity = explode(' ', $activity);
                $activity = implode(' ', array_filter($activity, function ($v) use ($shippingGoods) {
                    if ($v == $shippingGoods) {
                        return false;
                    }
                    return true;
                }, ARRAY_FILTER_USE_BOTH));

            } else {
                $activity = explode(' ', $activity);
                $activity = array_unique(array_merge($activity, [$shippingGoods]));
                $activity = implode(' ', $activity);
            }
        }

        $info = [
            'id' => $data['goods_id'],
            'activity' => $activity ?:$shippingGoods
        ];

        Log::debug('full_shipping_goods-debug', $info);

        return $info;
    }

    private static function formatGoodsTagInfo($type, $data)
    {
        if($type == self::TYPE_UPDATE) {
            return false;
        }

        $info = [
            'id' => $data['goods_id'],
            'heat_tag' => $data['tag'],
        ];

        Log::debug('goods_tag-debug', $info);

        return $info;
    }

    private static function formatCartInfo($type, $data, $primaryData)
    {
        if($type == self::TYPE_INSERT) {
            cGoodsAddCart::incrAddCartNumber($data['goods_id'], cGoodsAddCart::ADD_CART_TYPE_GOODS, $data['buy_num']);
            cGoodsAddCart::incrAddCartNumber($data['goods_id'], cGoodsAddCart::ADD_CART_TYPE_USER, 1);
        }

        if($type == self::TYPE_UPDATE) {
            if(isset($primaryData['buy_num'])) {
                if($data['buy_num'] > $primaryData['buy_num']) {
                    $number = $data['buy_num'] - $primaryData['buy_num'];
                    cGoodsAddCart::incrAddCartNumber($data['goods_id'], cGoodsAddCart::ADD_CART_TYPE_GOODS, $number);
                } elseif ($data['buy_num'] < $primaryData['buy_num']) {
                    $number = $primaryData['buy_num'] - $data['buy_num'];
                    cGoodsAddCart::decrAddCartNumber($data['goods_id'], cGoodsAddCart::ADD_CART_TYPE_GOODS, $number);
                }
            }
        }

        if(isset($primaryData['status'])) {
            if($data['status'] == 2) {
                cGoodsAddCart::decrAddCartNumber($data['goods_id'], cGoodsAddCart::ADD_CART_TYPE_GOODS, $data['buy_num']);
                cGoodsAddCart::decrAddCartNumber($data['goods_id'], cGoodsAddCart::ADD_CART_TYPE_USER, 1);
            }
        }

        if(($type == self::TYPE_UPDATE && $data['status'] == 0) && $primaryData['status'] == 2) {
            cGoodsAddCart::incrAddCartNumber($data['goods_id'], cGoodsAddCart::ADD_CART_TYPE_USER, 1);
        }

        $addCartNum = cGoodsAddCart::getGoodsAddCart($data['goods_id']);

        $info = [
            'id' => $data['goods_id'],
            'add_cart_num' => $addCartNum
        ];
        Log::debug('cart', $info);

        return $info;
    }

    private static function formatGoodsList($goodsList, $field)
    {
        $list = [];
        foreach ($goodsList as $value) {
            if(!is_array($field)) {
                $list[] = $value['_source'];
            } else if(count($field) == 1) {
                $list[] = $value['_source'][current($field)];
            } else {
                $list[] = $value['_source'];
            }
        }
        return $list;
    }

    private static function filterWhere(&$where)
    {
        if (HhzEnv::isProductionWithoutApi2() && gethostname() != 'hzv_biz_admin') {  // 线上 && 不是商城后台才会进行过滤
            // 如果没有根据shop_id查询的话，进行过滤
            if(!isset($where['shop_id'])) {
                // 如果条件中包含[shop_id[!]]的话，与测试店铺和限流店铺合并
                if(isset($where['shop_id[!]'])) {
                    $where['shop_id[!]'] = array_unique(array_merge($where['shop_id[!]'],IsTestShop::TEST_SHOP_IDS, LimitationShop::getAllShopIds()??[]));
                } else {
                    $where['shop_id[!]'] = array_unique(array_merge(IsTestShop::TEST_SHOP_IDS, LimitationShop::getAllShopIds()??[]));
                }
                $where['tags_content[!]'] = self::GOODS_TAG_SHIELD;
            }
            $where['stock'] = true;
            $where['app_status'] = 1;
        }

    }
}